package com.chinasofti.shoot;


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

//主程序类
public class ShootGame extends JPanel{
    public static final int WIDTH = 400;  //窗口宽
    public static final int HEIGHT = 654; //窗口高

    public static BufferedImage background; //背景图
    public static BufferedImage start;      //启动图
    public static BufferedImage pause;      //暂停图
    public static BufferedImage gameover;   //游戏结束图
    public static BufferedImage airplane;   //敌机
    public static BufferedImage bee;        //小蜜蜂
    public static BufferedImage bullet;     //子弹
    public static BufferedImage hero0;      //英雄机0
    public static BufferedImage hero1;      //英雄机1

    private Hero hero = new Hero(); //英雄机对象
    private FlyingObject[] flyings = {}; //敌人(敌机+小蜜蜂)数组
    private Bullet[] bullets = {}; //子弹数组

    private Timer timer;	//定时器
    private int intervel = 1000/100;	//时间间隔(毫秒)

    private int score = 0; //玩家的得分

    private int state;
    public static final int START = 0;     //启动状态
    public static final int RUNNING = 1;   //运行状态
    public static final int PAUSE = 2;     //暂停状态
    public static final int GAME_OVER = 3; //游戏结束状态



    static{ //加载图片
        try{
            background = ImageIO.read(ShootGame.class.getResource("background.png"));
            start = ImageIO.read(ShootGame.class.getResource("start.png"));
            pause = ImageIO.read(ShootGame.class.getResource("pause.png"));
            gameover = ImageIO.read(ShootGame.class.getResource("gameover.png"));
            airplane = ImageIO.read(ShootGame.class.getResource("airplane.png"));
            bee = ImageIO.read(ShootGame.class.getResource("bee.png"));
            bullet = ImageIO.read(ShootGame.class.getResource("bullet.png"));
            hero0 = ImageIO.read(ShootGame.class.getResource("hero0.png"));
            hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png"));
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /** 重写paint() g:画笔*/
    public void paint(Graphics g){
        g.drawImage(background,0,0,null); //画背景图
        paintHero(g); //画英雄机
        paintFlyingObjects(g); //画敌人(敌机+小蜜蜂)
        paintBullets(g); //画子弹
        paintScore(g); //画分数
        paintState(g); //画状态
    }
    /** 画英雄机对象 */
    public void paintHero(Graphics g){
        g.drawImage(hero.image,hero.x,hero.y,null); //画对象
    }
    /** 画敌人(敌机+小蜜蜂)对象 */
    public void paintFlyingObjects(Graphics g){
        for(int i=0;i<flyings.length;i++){ //遍历敌人(敌机+小蜜蜂)数组
            FlyingObject f = flyings[i]; //获取每一个敌人
            g.drawImage(f.image,f.x,f.y,null); //画敌人对象
        }
    }
    /** 画子弹对象 */
    public void paintBullets(Graphics g){
        for(int i=0;i<bullets.length;i++){ //遍历子弹数组
            Bullet b = bullets[i]; //获取每一个子弹
            g.drawImage(b.image,b.x,b.y,null); //画子弹对象
        }
    }
    /** 画分数 */
    public void paintScore(Graphics g){
        int x = 10;
        int y = 25;
        Font font = new Font(Font.SANS_SERIF,Font.BOLD,14);
        g.setColor(new Color(0x3A3B3B)); //设置颜色(纯红)
        g.setFont(font); //设置样式(字体:SANS_SERIF,样式:加粗,字号:24)
        g.drawString("分数: "+score,x,y); //画分
        y+=20;
        g.drawString("生命: "+hero.getLife(),x,y); //画命
    }
    /** 画状态 */
    public void paintState(Graphics g){
        switch(state){ //根据当前状态画不同的图
            case START: //启动状态时画启动图
                g.drawImage(start,0,0,null);
                break;
            case PAUSE: //暂停状态时画暂停图
                g.drawImage(pause,0,0,null);
                break;
            case GAME_OVER: //游戏结束状态时画游戏结束图
                g.drawImage(gameover,0,0,null);
                break;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Fly"); //创建一个Jframe对象
        ShootGame game = new ShootGame(); //创建一个JPanel对象
        frame.add(game); //将面板添加到框架中

        frame.setSize(WIDTH, HEIGHT); //设置窗口大小
        frame.setAlwaysOnTop(true); //设置总是在最上面
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置默认关闭操作(窗口关闭时退出程序)
        frame.setLocationRelativeTo(null); //设置居中显示
        frame.setVisible(true); //1.设置窗口可见  2.尽快调用paint()


        game.action();	//启动执行
    }

    /** 随机生成飞行物 */
    public FlyingObject nextOne(){
        Random rand = new Random(); //创建随机数对象
        int type = rand.nextInt(20); //生成0到19之间的随机数
        if(type==0){ //为0时返回蜜蜂对象
            return new Bee();
        }else{ //为1到19时返回敌机对象
            return new AirePlane();
        }
    }

    int flyEnteredIndex = 0; //敌人入场计数
    /** 敌人(敌机+小蜜蜂)入场 */
    public void enterAction(){ //10毫秒走一次
        flyEnteredIndex++; //每10毫秒增1
        if(flyEnteredIndex%30==0){ //400(10*40)毫秒走一次
            FlyingObject obj = nextOne(); //获取敌人(敌机+小蜜蜂)对象
            flyings = Arrays.copyOf(flyings,flyings.length+1); //扩容(扩大一个容量)
            flyings[flyings.length-1] = obj; //将敌人对象赋值给数组的最后一个元素
        }
    }

    /** 飞行物走一步 */
    public void stepAction(){ //10毫秒走一次
        hero.step(); //英雄机走一步
        for(int i=0;i<flyings.length;i++){ //遍历所有敌人
            flyings[i].step(); //每个敌人走一步
        }
        for(int i=0;i<bullets.length;i++){ //遍历所有子弹
            bullets[i].step(); //每个子弹走一步
        }
    }

    /** 启动程序的执行 */
    public void action(){
        MouseAdapter l = new MouseAdapter(){ //创建侦听器对象
            /** 鼠标移动事件 */
            public void mouseMoved(MouseEvent e){
                if(state==RUNNING){ //运行状态时执行
                    int x = e.getX();  //获取鼠标的x坐标
                    int y = e.getY();  //获取鼠标的y坐标
                    hero.moveTo(x, y); //英雄机随着鼠标动
                }
            }
            /** 鼠标点击事件 */
            public void mouseClicked(MouseEvent e){
                switch(state){ //不同状态时点击后有不同的反应
                    case START: //启动状态时
                        state = RUNNING; //当前状态变为运行状态
                        break;
                    case GAME_OVER: //游戏结束状态时
                        score = 0; //清理现场
                        hero = new Hero();
                        flyings = new FlyingObject[0];
                        bullets = new Bullet[0];
                        state = START; //当前状态变为启动状态
                        break;
                }
            }
            /** 鼠标移出事件 */
            public void mouseExited(MouseEvent e){
                if(state==RUNNING){ //运行状态时
                    state=PAUSE; //当前状态改为暂停状态
                }
            }
            /** 鼠标移入事件 */
            public void mouseEntered(MouseEvent e){
                if(state==PAUSE){ //暂停状态时
                    state=RUNNING; //当前状态改为运行状态
                }
            }
        };
        this.addMouseListener(l); //处理鼠标操作事件
        this.addMouseMotionListener(l); //处理鼠标滑动操作

        timer = new Timer(); //创建定时器对象
        timer.schedule(new TimerTask(){
            public void run(){ //10毫秒走一次--定时干的那个事
                if(state==RUNNING){ //运行状态时执行
                    enterAction(); //敌人(敌机+小蜜蜂)入场
                    stepAction();  //飞行物走一步
                    shootAction(); //英雄机发射子弹--子弹入场
                    bangAction();	//子弹与敌人的碰撞
                    outOfBoundsAction(); //删除越界的飞行物
                    checkGameOverAction(); //检测游戏是否结束
                }
                repaint();     //重画，调用paint()
            }
        },intervel,intervel);
    }

    int shootIndex = 0; //射击计数
    /** 英雄机发射子弹(子弹入场) */
    public void shootAction(){ //10毫秒走一次
        shootIndex++; //每10毫秒增1
        if(shootIndex%10==0){ //每300(10*30)毫秒走一次
            Bullet[] bs = hero.shoot(); //获取英雄机发射出来的子弹
            bullets = Arrays.copyOf(bullets, bullets.length+bs.length); //扩容(bs有几个元素就扩大几个容量)
            System.arraycopy(bs,0,bullets,bullets.length-bs.length,bs.length); //数组的追加(将bs追加到bullets数组中)
        }
    }

    /** 所有子弹与所有敌人撞 */
    public void bangAction(){ //10毫秒走一次
        for(int i=0;i<bullets.length;i++){ //遍历所有子弹
            Bullet b = bullets[i]; //获取每一个子弹
            bang(b); //一个子弹与所有敌人撞
        }
    }

    /** 一个子弹与所有敌人撞 */
    public void bang(Bullet b){
        int index = -1; //被撞敌人的下标
        for(int i=0;i<flyings.length;i++){ //遍历所有敌人
            FlyingObject f = flyings[i]; //获取每一个敌人
            if(f.shootBy(b)){ //撞上了
                index = i; //记录被撞敌人的下标
                break; //其余敌人不再比较
            }
        }
        if(index != -1){ //有撞上的
            FlyingObject one = flyings[index]; //获取被撞的敌人对象
            if(one instanceof Enemy){  //若被撞对象是敌人
                Enemy e = (Enemy)one;  //将被撞对象强转为敌人
                score += e.getScore(); //累加分数
            }
            if(one instanceof Award){   //若被撞对象是奖励
                Award a = (Award)one;   //将被撞对象强转为奖励
                int type = a.getType(); //获取奖励类型
                switch(type){ //根据type的不同取值获取相应的奖励
                    case Award.DOUBLE_FIRE:   //奖励类型为火力时
                        hero.addDoubleFire(); //英雄机增火力
                        break;
                    case Award.LIFE:    //奖励类型为命时
                        hero.addLife(); //英雄机增命
                        break;
                }
            }
            //交换被撞敌人对象与数组中的最后一个元素
            FlyingObject t = flyings[index];
            flyings[index] = flyings[flyings.length-1];
            flyings[flyings.length-1] = t;
            //缩容(去掉最后一个元素，即:被撞敌人对象)
            flyings = Arrays.copyOf(flyings, flyings.length-1);
        }
    }



    /** 删除越界的飞行物 */
    public void outOfBoundsAction(){
        int index = 0; //1.不越界敌人数组下标  2.不越界敌人个数
        FlyingObject[] flyingLives = new FlyingObject[flyings.length]; //不越界敌人数组
        for(int i=0;i<flyings.length;i++){ //遍历所有敌人
            FlyingObject f = flyings[i]; //获取每一个敌人
            if(!f.outOfBounds()){ //不越界
                flyingLives[index] = f; //将不越界敌人添加到不越界敌人数组中
                index++; //1.下标增一  2.不越界敌人个数增一
            }
        }
        flyings = Arrays.copyOf(flyingLives, index); //将不越界敌人复制到flyings数组中，index为flyings的新长度

        index = 0; //1.下标归零  2.不越界个数归零
        Bullet[] bulletLives = new Bullet[bullets.length]; //不越界子弹数组
        for(int i=0;i<bullets.length;i++){ //遍历所有子弹
            Bullet b = bullets[i]; //获取每一个子弹
            if(!b.outOfBounds()){ //不越界
                bulletLives[index] = b; //将不越界子弹添加到不越界子弹数组中
                index++; //1.下标增一  2.不越界子弹个数增一
            }
        }
        bullets = Arrays.copyOf(bulletLives, index); //将不越界敌人复制到bullets数组中，index为bullets的新长度
    }

    /** 判断游戏是否结束  返回true表示游戏结束 */
    public boolean isGameOver(){
        for(int i=0;i<flyings.length;i++){ //遍历所有敌人
            FlyingObject f = flyings[i]; //获取每一个敌人
            if(hero.hit(f)){ //撞上了
                hero.subtractLife(); //英雄机减命
                hero.setDoubleFire(0); //英雄机清火力
                //交换被撞敌人与数组的最后一个元素
                FlyingObject t = flyings[i];
                flyings[i] = flyings[flyings.length-1];
                flyings[flyings.length-1] = t;
                //缩容(去掉最后一个元素，即:被撞的敌人对象)
                flyings = Arrays.copyOf(flyings,flyings.length-1);
            }
        }
        return hero.getLife()<=0; //命数<=0，即为游戏结束
    }

    /** 检测游戏是否结束 */
    public void checkGameOverAction(){
        if(isGameOver()){ //游戏结束时
            state = GAME_OVER; //当前状态改为游戏结束状态
        }
    }



}